package com.wentao.thisService.controller;

import com.wentao.thisCommon.common.ConvertEntity;
import com.wentao.thisCommon.model.RequestBase;
import com.wentao.thisCommon.model.ResultBase;
import com.wentao.thisFacade.business.PayCtrInterface;
import com.wentao.thisFacade.common.enums.SuccessCode;
import com.wentao.thisFacade.domain.reqeust.PayRequest;
import com.wentao.thisFacade.domain.reqeust.WxH5SceneRequest;
import com.wentao.thisFacade.domain.reqeust.WxPayRequest;
import com.wentao.thisFacade.domain.result.WxPayConvertResult;
import com.wentao.thisFacade.domain.result.WxPayResult;
import com.wentao.thisFacade.domain.result.WxTokenResult;
import com.wentao.thisService.common.CommonFunction;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RestController;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.util.*;

@RestController
public class PayController implements PayCtrInterface {

    @Value("${pay.wx.appid}")
    private String appid;

    @Value("${pay.wx.mch_id}")
    private String mch_id;

    @Value("${pay.wx.url.apply}")
    private String apply_url;

    @Value("${pay.wx.url.redirect}")
    private String redirect_url;

    @Value("${pay.wx.url.authorize}")
    private String authorize_url;

    @Value("${pay.wx.url.token}")
    private String token_url;

    @Value("${pay.wx.dev_appid}")
    private String dev_appid;

    @Value("${pay.wx.dev_secret}")
    private String dev_secret;

    @Value("${pay.wx.mch_key}")
    private String mch_key;

    @Value("${pay.wx.scene.h5.type}")
    private String scene_h5_type;

    @Value("${pay.wx.scene.h5.wap_url}")
    private String scene_h5_url;

    @Value("${pay.wx.scene.h5.wap_name}")
    private String scene_h5_name;

    /**
     * @see PayCtrInterface#wxPay(RequestBase)
     */
    @Override
    public ResultBase<WxPayResult> wxPay(RequestBase<PayRequest> entity) throws Exception {
//        WxTokenResult result = wxPayAuthorize();
        String expire_time = CommonFunction.GetLocalDateString(CommonFunction.AddDateTime(1000 * 60 * 10), "yyyyMMddHHmmss");
        WxPayRequest wxPayRequest = (WxPayRequest) ConvertEntity.copyEntity(entity.getBody(), WxPayRequest.class);
        wxPayRequest.setAppid(appid);
        wxPayRequest.setMch_id(mch_id);
//        wxPayRequest.setOpenid(result.getOpenid());
        wxPayRequest.setNonce_str(UUID.randomUUID().toString().replace("-", ""));
        wxPayRequest.setFee_type("CNY");
        wxPayRequest.setSign_type("MD5");
        wxPayRequest.setTrade_type("MWEB");
        wxPayRequest.setTime_expire(expire_time);
        wxPayRequest.setScene_info(createScene());
        wxPayRequest.setTime_start(CommonFunction.GetLocalDateString(new Date(), "yyyyMMddHHmmss"));
        wxPayRequest.setSign(wxSign(wxPayRequest));
        String xml = ConvertEntity.convertToXml(wxPayRequest);
//        WxPayResult rtn = CommonFunction.RunUrlXmlBody(apply_url, xml, WxPayResult.class);
        String response = CommonFunction.RunUrlBody(apply_url, xml);
//        WxPayResult rtn = ConvertEntity.converyToJavaBean(response, WxPayResult.class);
        Unmarshaller unmarshaller = JAXBContext.newInstance(WxPayConvertResult.class).createUnmarshaller();
        Object rtn = unmarshaller.unmarshal(new StringReader(response));
        WxPayConvertResult wxPayConvertResult = (WxPayConvertResult) rtn;
        return ResultBase.ok(rtn, SuccessCode.SYSTEM_SUCCESS);
    }

    private String createScene() {
        WxH5SceneRequest wxH5SceneRequest = new WxH5SceneRequest();
        wxH5SceneRequest.setType(scene_h5_type);
        wxH5SceneRequest.setWap_name(scene_h5_name);
        wxH5SceneRequest.setWap_url(scene_h5_url);
        Map<String, WxH5SceneRequest> scene = new HashMap<>();
        scene.put("h5_info", wxH5SceneRequest);
        return ConvertEntity.javaToJson(scene);
    }

    private WxTokenResult wxPayAuthorize() throws Exception {
        Map<String, String> payCodeMap = new HashMap<>();
        payCodeMap.put("appid", dev_appid);
        payCodeMap.put("redirect_uri", redirect_url);
        payCodeMap.put("response_type", "code");
        payCodeMap.put("scope", "snsapi_userinfo");
        payCodeMap.put("state", "STATE#wechat_redirect");
        String code = CommonFunction.RunStringGetUrl(authorize_url, payCodeMap);
        payCodeMap.clear();
        payCodeMap.put("appid", dev_appid);
        payCodeMap.put("secret", dev_secret);
        payCodeMap.put("code", code);
        payCodeMap.put("grant_type", "authorization_code");
        WxTokenResult wxTokenResult = CommonFunction.RunGetUrl(token_url, payCodeMap, WxTokenResult.class);
        return wxTokenResult;
    }

    private String wxSign(WxPayRequest wxPayRequest) {
        Map<String, String> wxMap = ConvertEntity.CovertToMap(wxPayRequest);
        Object[] wxKeys = wxMap.keySet().toArray();
        Arrays.sort(wxKeys);
        StringBuilder sb = new StringBuilder();
        for (Object key : wxKeys) {
            if (sb.length() > 0) {
                sb.append(String.format("&%s=%s", key, wxMap.get(key)));
            } else {
                sb.append(String.format("%s=%s", key, wxMap.get(key)));
            }
        }
        sb.append(String.format("&key=%s", mch_key));
        String sign = CommonFunction.CreateMd5(sb.toString()).toUpperCase();
        return sign;
    }
}
